<!-- 主体结构树 -->

<template>
  <EasyCard v-if="hasTree || hasOrgan || hasRegion" class="CommonBody-BodyTree" full :width="leftWidth" noPadding>
    <EasyTreeMulti
      v-if="multi"
      v-model="model"
      v-bind="treeProps"
      @idChange="emitChange"
      @expand="toExpand"
      @collapse="toCollapse"
    >
      <template #top>
        <slot name="treeTop" />
      </template>

      <template #default="{ data, node, nodeClass }">
        <slot name="treeNode" :data="data" :node="node" :nodeClass="nodeClass" />
      </template>

      <template #bottom>
        <slot name="treeBottom" />
      </template>
    </EasyTreeMulti>

    <EasyTree
      v-else
      v-model="model"
      v-bind="treeProps"
      @idChange="emitChange"
      @expand="toExpand"
      @collapse="toCollapse"
    >
      <template #top>
        <slot name="treeTop" />
      </template>

      <template #default="{ data, node, nodeClass }">
        <slot name="treeNode" :data="data" :node="node" :nodeClass="nodeClass" />
      </template>

      <template #bottom>
        <slot name="treeBottom" />
      </template>
    </EasyTree>
  </EasyCard>
</template>

<script>
// ============================== 导入依赖 ============================== //

import CORE from '@/CORE'
import props from '../props'
import { transTreeMap } from '@root/【CORE】/STORE/TREE'

// ============================== 导出组件 ============================== //

export default {
  /**
   * 名称定义 (实际使用名称)
   */
  name: 'BodyTree',

  /**
   * 属性注册 (抽取以便查阅)
   */
  props,

  /**
   * 状态数据 (函数返回对象)
   */
  data() {
    return {
      model: undefined, // 内部绑定值
      EMPTY: undefined, // 空值常量
    }
  },

  /**
   * 计算属性 (慎用箭头函数)
   */
  computed: {
    /**
     * 原始结构树
     */
    initTree() {
      if (this.hasTree) return this.tree
      if (this.hasOrgan) return this.organ || CORE.ORGAN.TREE
      if (this.hasRegion) return this.region || CORE.REGION.MY_TREE
      return []
    },

    /**
     * 结构树映射
     */
    treeMap() {
      const { initTree, field } = this
      return transTreeMap({}, initTree, field)
    },

    /**
     * 原始提示
     */
    initTip() {
      const { hasTree, hasOrgan, hasRegion, filterTip } = this
      const organName = `${CORE.MAP.ORGAN}名称`
      const regionName = `${CORE.MAP.REGION}名称`
      const initTip = hasTree ? filterTip || '请输入名称' : hasOrgan ? organName : hasRegion ? regionName : ''
      return initTip
    },

    /**
     * 结构树属性
     */
    treeProps() {
      const { initTree, treeMap, rootId, expandAll, noExpand, initTip } = this
      return {
        tree: rootId ? [treeMap[rootId]] : initTree,
        filterTip: initTip,
        field: this.field,
        initRoot: this.initRoot,
        initFirst: this.initFirst,
        hasReset: this.hasReset,
        expandOnClick: this.expandOnClick,
        expandAll: !noExpand && expandAll,
        expandRoot: !noExpand && !expandAll,
      }
    },

    /**
     * 所属对象
     */
    obj() {
      const { param, bind, $store } = this
      if (param) return param
      if ($store && $store.state.param) return $store.state.param
      return { [bind]: '' }
    },

    /**
     * 是否有页头
     */
    hasHeader() {
      if (!this.$scopedSlots) return false
      return this.$scopedSlots.header
    },

    /**
     * 是否有页脚
     */
    hasFooter() {
      if (!this.$scopedSlots) return false
      return this.$scopedSlots.footer
    },
  },

  /**
   * 监听属性 (深度 deep 首次 immediate)
   */
  watch: {
    /**
     * 监听所属对象
     */
    obj: {
      deep: true,
      immediate: true,
      handler() {
        const { isDiff, setModel, emitChange } = this
        if (isDiff()) {
          setModel()
          emitChange()
        }
      },
    },
  },

  /**
   * 创建完成 (先抽取再调用)
   */
  created() {
    const { obj, bind, $set } = this
    if (!Object.keys(obj).includes(bind)) $set(obj, bind, '')
  },

  /**
   * 本地方法 (轻量重要在前)
   */
  methods: {
    /**
     * 是否不等 (可覆盖)
     */
    isDiff() {
      const { obj, bind, model } = this
      // 判断是否有值
      if (obj[bind]) return obj[bind] !== model
      else return model
    },

    /**
     * 设置内部绑定值 (可覆盖)
     */
    setModel() {
      const { obj, bind, EMPTY } = this
      this.model = obj[bind] || EMPTY
    },

    /**
     * 获取最终回传值 (可覆盖)
     */
    getValue() {
      const { model } = this
      return model
    },

    /**
     * 是否相等 (可覆盖)
     */
    equals(value) {
      const { obj, bind } = this
      return obj[bind] === value
    },

    /**
     * 提交改变 (可覆盖)
     */
    emitChange() {
      const { getValue, equals, obj, bind, treeMap } = this

      // 获取新值
      const value = getValue()

      // 判断改变
      if (equals(value)) return

      // 更新绑定
      this.$set(obj, bind, value)
      this.$emit('change', treeMap[value] || {})
    },

    /**
     * 点击展开
     */
    toExpand(data) {
      this.$emit('expand', data)
    },

    /**
     * 点击收缩
     */
    toCollapse(data) {
      this.$emit('collapse', data)
    },
  },
}
</script>
